package com.xiaoleilu.hutool.crypto.symmetric; import com.xiaoleilu.hutool.crypto.CryptoException; import com.xiaoleilu.hutool.crypto.SecureUtil; import com.xiaoleilu.hutool.io.IoUtil; import com.xiaoleilu.hutool.util.CharsetUtil; import com.xiaoleilu.hutool.util.HexUtil; import com.xiaoleilu.hutool.util.RandomUtil; import com.xiaoleilu.hutool.util.StrUtil; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.PBEParameterSpec; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import java.security.spec.AlgorithmParameterSpec; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 对称加密算法<br> * @author Looly * */ public class SymmetricCrypto { /** SecretKey 负责保存对称密钥 */ private SecretKey secretKey; /** Cipher负责完成加密或解密工作 */ private Cipher clipher; /** 加密解密参数 */ private AlgorithmParameterSpec params; private Lock lock = new ReentrantLock(); //------------------------------------------------------------------ Constructor start /** * 构造,使用随机密钥 * @param algorithm {@link SymmetricAlgorithm} */ public SymmetricCrypto(SymmetricAlgorithm algorithm) { this(algorithm, null); } /** * 构造,使用随机密钥 * @param algorithm 算法 */ public SymmetricCrypto(String algorithm) { this(algorithm, null); } /** * 构造 * @param algorithm 算法 {@link SymmetricAlgorithm} * @param key 自定义KEY */ public SymmetricCrypto(SymmetricAlgorithm algorithm, byte[] key) { this(algorithm.getValue(), key); } /** * 构造 * @param algorithm 算法 * @param key 密钥 */ public SymmetricCrypto(String algorithm, byte[] key) { init(algorithm, key); } //------------------------------------------------------------------ Constructor end /** * 初始化 * @param algorithm 算法 * @param key 密钥,如果为<code>null</code>自动生成一个key * @return {@link SymmetricCrypto} */ public SymmetricCrypto init(String algorithm, byte[] key) { return init(algorithm, SecureUtil.generateKey(algorithm, key)); } /** * 初始化 * @param algorithm 算法 * @param key 密钥,如果为<code>null</code>自动生成一个key * @return {@link SymmetricCrypto} */ public SymmetricCrypto init(String algorithm, SecretKey key) { this.secretKey = key; if(algorithm.startsWith("PBE")){ //对于PBE算法使用随机数加盐 this.params = new PBEParameterSpec(RandomUtil.randomBytes(8), 100); } try { clipher = Cipher.getInstance(algorithm); } catch (Exception e) { throw new CryptoException(e); } return this; } //--------------------------------------------------------------------------------- Encrypt /** * 加密 * @param data 被加密的bytes * @return 加密后的bytes */ public byte[] encrypt(byte[] data){ lock.lock(); try { if(null == this.params){ clipher.init(Cipher.ENCRYPT_MODE, secretKey); }else{ clipher.init(Cipher.ENCRYPT_MODE, secretKey, params); } return clipher.doFinal(data); } catch (Exception e) { throw new CryptoException(e); }finally{ lock.unlock(); } } /** * 加密 * @param data * @return 加密后的Hex */ public String encryptHex(byte[] data){ return HexUtil.encodeHexStr(encrypt(data)); } /** * 加密 * @param data 被加密的字符串 * @param charset 编码 * @return 加密后的bytes */ public byte[] encrypt(String data, String charset){ return encrypt(StrUtil.bytes(data, charset)); } /** * 加密 * @param data 被加密的字符串 * @param charset 编码 * @return 加密后的Hex */ public String encryptHex(String data, String charset){ return HexUtil.encodeHexStr(encrypt(data, charset)); } /** * 加密,使用UTF-8编码 * @param data 被加密的字符串 * @return 加密后的bytes */ public byte[] encrypt(String data){ return encrypt(StrUtil.bytes(data, CharsetUtil.CHARSET_UTF_8)); } /** * 加密,使用UTF-8编码 * @param data 被加密的字符串 * @return 加密后的Hex */ public String encryptHex(String data){ return HexUtil.encodeHexStr(encrypt(data)); } /** * 加密 * @param data 被加密的字符串 * @return 加密后的bytes */ public byte[] encrypt(InputStream data){ try { return encrypt(IoUtil.readBytes(data)); } catch (IOException e) { throw new CryptoException(e); } } /** * 加密 * @param data 被加密的字符串 * @return 加密后的Hex */ public String encryptHex(InputStream data){ return HexUtil.encodeHexStr(encrypt(data)); } //--------------------------------------------------------------------------------- Decrypt /** * 解密 * @param bytes 被解密的bytes * @return 解密后的bytes */ public byte[] decrypt(byte[] bytes){ lock.lock(); try { if(null == this.params){ clipher.init(Cipher.DECRYPT_MODE, secretKey); }else{ clipher.init(Cipher.DECRYPT_MODE, secretKey, params); } return clipher.doFinal(bytes); } catch (Exception e) { throw new CryptoException(e); }finally{ lock.unlock(); } } /** * 解密 * @param bytes 被解密的bytes * @param charset 解密后的charset * @return 解密后的String */ public String decryptStr(byte[] bytes, Charset charset){ return StrUtil.str(decrypt(bytes), charset); } /** * 解密 * @param bytes 被解密的bytes * @return 解密后的String */ public String decryptStr(byte[] bytes){ return decryptStr(bytes, CharsetUtil.CHARSET_UTF_8); } /** * 解密 * @param data 被解密的String * @return 解密后的bytes */ public byte[] decrypt(String data) { return decrypt(HexUtil.decodeHex(data)); } /** * 解密 * @param data 被解密的String * @param charset 解密后的charset * @return 解密后的String */ public String decryptStr(String data, Charset charset){ return StrUtil.str(decrypt(data), charset); } /** * 解密 * @param data 被解密的String * @return 解密后的String */ public String decryptStr(String data){ return decryptStr(data, CharsetUtil.CHARSET_UTF_8); } /** * 解密 * @param data 被解密的bytes * @return 解密后的bytes */ public byte[] decrypt(InputStream data){ try { return decrypt(IoUtil.readBytes(data)); } catch (IOException e) { throw new CryptoException(e); } } /** * 解密 * @param data 被解密的InputStream * @param charset 解密后的charset * @return 解密后的String */ public String decryptStr(InputStream data, Charset charset){ return StrUtil.str(decrypt(data), charset); } /** * 解密 * @param data 被解密的InputStream * @return 解密后的String */ public String decryptStr(InputStream data){ return decryptStr(data, CharsetUtil.CHARSET_UTF_8); } //--------------------------------------------------------------------------------- Getters /** * 获得对称密钥 * @return 获得对称密钥 */ public SecretKey getSecretKey() { return secretKey; } /** * 获得加密或解密器 * @return 加密或解密 */ public Cipher getClipher() { return clipher; } }